﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Runtime.Remoting.Contexts;
using System.Threading.Tasks;
using CommonTools;
using CommonTools.Basic;
using shop.Model;

namespace shop.Bll.BasicInfo
{
    /// <summary> 基础资料基类 </summary>
    public abstract class BasicBllParent : CommonTools.Basic.IBasicBll
    {

        /// <summary> 查询 </summary>
        public abstract IEnumerable<object> Query(string code, bool isDetails, out string err);
         

        public abstract bool AddGroup(object obj, IUser user, out string err);
        public abstract bool DeleteGroup(object obj, IUser user, out string err);
        public abstract bool UpdateGroup(object obj, IUser user, out string err);

        public abstract bool Insert(object obj, IUser user, out string err);
        public abstract bool Update(object obj, IUser user, out string err);
        public abstract bool Delete(object obj, IUser user, out string err);



        public object CreateDefault()
        {
            return null;
        }


        /// <summary> 审核 </summary>
        public abstract bool Check(object obj, IUser user, out string err);

        /// <summary> 反审核 </summary>
        public abstract bool UnCheck(object obj, IUser user, out string err);


        /// <summary> 查询所有分组 </summary>
        public abstract IEnumerable<IFastTree> QueryTreeList();


        /// <summary> 代码中级别的分隔符 </summary>
        public abstract string Separator { get; }



        #region 导出导入


        /// <summary> 导出, 返回两个List, 第一个是分组的表, 第二个是明细的表 </summary>
        public async virtual Task<Result<IEnumerable<object>[]>> Export(IUser user)
        {
            var res = await Task.Run(() =>
            {
                //先查询分组信息
                var data1 = Query(string.Empty, false, out var err1);

                //再查询明细信息
                var data2 = Query(string.Empty, true, out var err2);


                //合并结果

                var err = string.Join(",", err1, err2).Trim(',');

                return new Result<IEnumerable<object>[]>(true, err, new[] { data1, data2 });
            });

            return res;
        }


        /// <summary> 导入 </summary>
        /// <remarks>todo 导入的数据需要做检查, 返回结果是原始数据加上两列:导入结果(是否成功),错误原因(类型错误, 不符合规范, 已经存在) </remarks>
        /// <param name="data">数据</param>
        /// <param name="user">用户</param>
        /// <param name="stopWhenError">出现错误时是否停止继续导入</param>
        /// <param name="err">错误消息</param>
        /// <returns></returns>
        public async virtual Task<IEnumerable<Result<object>>> ImportAsync<T>(IEnumerable<T> data, IUser user, bool stopWhenError)
        {
            var res = await Task.Run(() =>
            {
                return ImportInner(data, user, stopWhenError);
            });

            return res;
        }

        /// <summary> 同步方式导入 </summary>
        public virtual IEnumerable<Result<object>> Import<T>(IEnumerable<T> data, IUser user, bool stopWhenError)
        {
            return ImportInner(data, user, stopWhenError);
        }


        private IEnumerable<Result<object>> ImportInner<T>(IEnumerable<T> data, IUser user, bool stopWhenError)
        {
            int c = 0;
            foreach (var item in data)
            {
                var res = this.Insert(item, user, out var err);
                yield return new Result<object>(res, err, c++);

                //出错就停止
                if (res == false && stopWhenError)
                {
                    break;
                }
            }
        }



        /// <summary> 检查有没有上级代码 </summary>
        public virtual bool HaveUpperGroup<T>(T model, Expression<Func<T, bool>> exp)
            where T : class, IFastTree
        {

            //检查有没有上级代码
            if (string.IsNullOrEmpty(this.Separator) == false && model.Code.Contains(this.Separator))
            {
                var upperCode = model.Code.Substring(0, model.Code.IndexOf(this.Separator));
                var haveUppper = DB.FSql.Select<T>()
                    .Where(exp)
                    .Any(a => a.Code == upperCode);

                if (haveUppper == false)
                {
                    //return new Result(false, CN.Msg_NoUpperClassification);
                    return false;
                }
            }

            //return new Result(true);
            return true;
        }


        #endregion




        #region 权限

        /// <summary> 查询导出权限 </summary>
        public abstract string LookRight { get; }

        /// <summary> 保存权限 </summary>
        public abstract string SaveRight { get; }

        ///// <summary> 修改别人单据权限 </summary>
        //public abstract string ModifyRight { get; }

        ///// <summary> 删除别人单据权限 </summary>
        //public abstract string DeleteRight { get; }

        /// <summary> 审核,反审核权限 </summary>
        public abstract string CheckRight { get; }

        #endregion



        #region 调用图片管理

        /// <summary> 打开图片管理窗口 </summary>
        public event Action<object, string, CommonTools.IimgManger, Type> OpenImageManForm;


        public void OnOpenImageManForm(object item, string imgId, CommonTools.IimgManger bll, Type type)
        {
            this.OpenImageManForm?.Invoke(item, imgId, bll, type);
        }
        #endregion

    }




}
